home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
t3_1
/
vaxt.lha
/
vaxt
/
tsystem
/
dynload.c
next >
Wrap
C/C++ Source or Header
|
1987-12-30
|
11KB
|
405 lines
/*
* D Y N L O A D . C
*
* This file contains functions to help dynamically load foreign UNIX files
* into a running T process.
*
* written by Dorab Patel <dorab@neptune.cs.ucla.edu>
* December 24, 1986
* Copyright Dorab Patel (C) 1986
* Permission is given to distribute this software free to anyone
* using it for a non-commercial purpose. Comments/bug reports/fixes
* are encouraged.
*
* $Revision: 1.1 $
*
* $Log: dynload.c,v $
* Revision 1.1 86/12/24 18:20:44 dorab
* Initial Revision
*
*/
#ifndef lint
static char RCSid[] = "@(#)$Header: dynload.c,v 1.1 86/12/24 18:20:44 dorab UCLA $ (Exp)";
#endif
#include <stdio.h> /* for obvious reasons */
#include <a.out.h> /* for obvious reasons */
#include <sys/types.h> /* for caddr_t */
#include <strings.h> /* for strlen */
/*
* dont turn this on unless you want copious debugging.
* it may also have unwanted interactions with sbrk.
*/
#undef DEBUG
/*
* alloca is used by default for efficiency. if you need to use
* malloc, then define USE_MALLOC
*/
#undef USE_MALLOC
/* forward declarations */
caddr_t sbrk();
char *sprintf();
#ifdef USE_MALLOC
char *malloc();
#else ~USE_MALLOC
char *alloca();
#endif ~USE_MALLOC
/*
* loadhelp takes an object file (objFile), and loads it
* into the current process, using relocation information found in the
* namelist of relocFile. In the process, it will create
* tmpFile, which has all the current relocation info and which can
* be used for a subsequent load. In addition, libString
* is used to search any required libraries.
* otherString can be used for other ld arguments.
* Returns 0 if all ok, >0 otherwise.
* It closes all files it has opened and unlinks the temp file
* if there has been an error.
*
* TODO:
* do i need to round up the text/data sizes to word boundaries ?
*/
/*
* the sprintf string for the ld command
* if this changes, also modify the code for ldCmdSpace
*/
#define LoadCommandTemplate "/bin/ld -N -x -A %s -T %lx %s %s -o %s %s -lc"
int
loadhelp(objFile, relocFile, tmpFile, libString, otherString)
char *objFile, *relocFile, *tmpFile, *libString, *otherString;
{
char *loadCommand; /* pointer to string containing the ld cmd */
int ldCmdSpace; /* space allocated for ld command */
char buf[BUFSIZ]; /* for buffering tmpFile i/o */
struct exec hdr;
long loadPoint, endOfMem, pageSize, tmp;
FILE *tmpFD = NULL;
long bytesToRead, bytesToExtend;
/*
* calculate the length of the ld command and allocate memory for it
* this code would need changing if LoadCommandTemplate was changed
*/
ldCmdSpace = strlen(LoadCommandTemplate);
ldCmdSpace += strlen(objFile) + strlen(relocFile) + strlen(tmpFile);
ldCmdSpace += strlen(libString) + strlen(otherString);
ldCmdSpace += 16; /* 10 for loadPoint + 1 for null + fudge of 5 */
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: ld cmd needs %d bytes\n", ldCmdSpace);
#endif DEBUG
#ifdef USE_MALLOC
loadCommand = malloc((unsigned)ldCmdSpace);
#else ~USE_MALLOC
loadCommand = alloca(ldCmdSpace);
#endif ~USE_MALLOC
if ((long)loadCommand == 0) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,
"loadhelp: could not allocate %d bytes for ld cmd\n",
ldCmdSpace);
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(1);
}
pageSize = (long) getpagesize(); /* works on vaxen and suns */
/* there is a strong assumption that pageSize is a power of 2 */
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: page size is %ld (%lx)\n", pageSize, pageSize);
#endif DEBUG
endOfMem = (long) sbrk(0); /* get end of current memory */
if (endOfMem < 0) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: sbrk(0) failed\n");
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(2);
}
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: end of memory = %ld (%lx)\n",
endOfMem, endOfMem);
#endif DEBUG
/* round up to the next higher pageSize */
loadPoint = (long) sbrk((int)(pageSize - (endOfMem & (pageSize - 1L))));
if (loadPoint < 0L) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: could not bump upto pagesize\n");
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(3);
}
loadPoint = (long) sbrk(0);
/*
* there had better be no further calls to sbrk explicitly or implicitly
* (e.g. via calling printf or something like that) until the loading is
* over.
*/
/* sanity check */
if (loadPoint < 0L || ((loadPoint & (pageSize - 1L)) != 0L)) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: not page aligned\n");
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(4);
}
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: load point is %ld (%lx)\n",
loadPoint, loadPoint);
#endif DEBUG
(void)sprintf(loadCommand, LoadCommandTemplate,
relocFile, loadPoint, otherString, objFile, tmpFile, libString);
/* if the sprintf overflows it'll probably botch BAD, but just in case */
if (strlen(loadCommand) >= ldCmdSpace) {
#ifdef DEBUG
(void)fprintf(stderr,
"loadhelp: load command greater than %d byte buffer\n",
ldCmdSpace);
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(5);
}
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: the load command is \"%s\"\n", loadCommand);
#endif DEBUG
/* run the ld comand to do relocation */
if (system(loadCommand) != 0 ) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: error in executing the ld command\n");
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(6);
}
/* open the relocated file */
tmpFD = fopen(tmpFile, "r");
if (tmpFD == NULL ) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr, "loadhelp: could not open %s for read\n",
tmpFile);
#endif DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(7);
}
/*
* use buf to buffer tmpFile so that no mallocs can occur
* since buf is automatic, tmpFD must be closed upon exit from this routine
*/
(void)setbuf(tmpFD,buf);
/* read its header */
if (fread((char *)&hdr, sizeof(struct exec), 1, tmpFD) != 1) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: error reading header of %s\n", tmpFile);
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(8);
}
if (N_BADMAG(hdr)) {
#ifdef DEBUG
(void)fprintf(stderr,"loadhelp: bad magic number %o in %s\n",
hdr.a_magic, tmpFile);
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(9);
}
#ifdef DEBUG
(void)fprintf(stderr,
"loadhelp: magic = %o, text = %ld(%lx), data = %ld(%lx), bss = %ld(%lx)\n",
hdr.a_magic, hdr.a_text,
hdr.a_text, hdr.a_data,
hdr.a_data, hdr.a_bss, hdr.a_bss);
#endif DEBUG
bytesToRead = hdr.a_text + hdr.a_data;
bytesToExtend = bytesToRead + hdr.a_bss;
#ifdef DEBUG
(void)fprintf(stderr,
"loadhelp: going to read %ld bytes and extend by %ld bytes\n",
bytesToRead, bytesToExtend);
#endif DEBUG
/* get required memory */
tmp = (long) sbrk((int)bytesToExtend);
if (tmp < 0L) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: not enough memory\n");
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(10);
}
/* some last sanity checks */
if (tmp != loadPoint) {
#ifdef DEBUG
(void)fprintf(stderr,
"loadhelp: load point is %ld but sbrk returns %ld\n",
loadPoint, tmp);
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(11);
}
if (tmp & (pageSize - 1L)) {
#ifdef DEBUG
(void)fprintf(stderr,
"loadhelp: allocated memory at %ld -not page aligned\n");
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(12);
}
/* go to beginning of text */
if (fseek(tmpFD,(long)N_TXTOFF(hdr),0) < 0) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr,"loadhelp: fseek failed on %s\n", tmpFile);
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(13);
}
/* read the text and data segments in */
if (fread((char *)loadPoint, 1, (int)bytesToRead, tmpFD) != (int)bytesToRead) {
#ifdef DEBUG
perror("loadhelp");
(void)fprintf(stderr, "loadhelp: could not read data from %s\n",
tmpFile);
if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
#else ~DEBUG
(void)fclose(tmpFD); /* close tmp file */
(void)unlink(tmpFile); /* remove it */
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(14);
}
#ifdef DEBUG
if (fclose(tmpFD) == EOF) perror("loadhelp");
#else ~DEBUG
(void)fclose(tmpFD);
#endif ~DEBUG
#ifdef USE_MALLOC
free(loadCommand);
#endif USE_MALLOC
return(0);
}
/*
* return the address of the function functionName in the namelist
* of the file fileName.
* the calling procedure had better make sure that fileName exists.
*/
unsigned long
nlistone(fileName,functionName)
char *fileName, *functionName;
{
struct nlist nl[2];
int rc;
nl[1].n_un.n_name = '\0'; /* terminate the name list */
nl[0].n_un.n_name = functionName; /* put the function name in */
rc = nlist(fileName,nl); /* call nlist */
if (rc < 0 || (nl[0].n_type == (unsigned char) 0 /* check for errors */
&& nl[0].n_value == (unsigned long) 0))
return ((unsigned long) 0);
if (nl[0].n_type & N_TEXT) /* if it is in the text segment i.e. is a function */
return(nl[0].n_value); /* return the address */
else
return ((unsigned long) 0); /* not a function */
}